/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.editor.java;
import java.awt.Dialog;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ResourceBundle;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import org.netbeans.editor.ext.JCClass;
import org.netbeans.editor.ext.JCompletion;
import org.netbeans.editor.ext.JCUtilities;
import org.openide.src.ClassElement;
import org.openide.src.ConstructorElement;
import org.openide.src.MethodElement;
import org.openide.src.FieldElement;
import org.openide.src.Identifier;
import org.openide.src.SourceElement;
import org.openide.src.Type;
import org.openide.src.MethodParameter;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataFolder;
import org.openide.nodes.Node;
import org.openide.cookies.SourceCookie;
import org.openide.filesystems.FileObject;
import org.openide.TopManager;
import org.openide.DialogDescriptor;
import org.openide.util.NbBundle;
import org.openide.util.HelpCtx;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileSystem;
import org.openide.util.enum.QueueEnumeration;
/**
* Updating of JC classes
*
* @author Miloslav Metelka
* @version 1.00
*/
public class JCUpdater extends Thread {
private static ResourceBundle bundle;
private static final String BUNDLE_TITLE = "JC_title"; // NOI18N
private static final String BUNDLE_INSPECTING = "JC_inspecting"; // NOI18N
private static final String BUNDLE_BUILDING_CLASS = "JC_building_class"; // NOI18N
private static final String BUNDLE_INIT_PARSER = "JC_init_parser"; // NOI18N
private static final String BUNDLE_UPDATING_DB = "JC_updating_db"; // NOI18N
private static final String BUNDLE_UPDATING_MEMORY = "JC_updating_memory"; // NOI18N
private static final String BUNDLE_ENTRIES = "JC_entries"; // NOI18N
private static final String BUNDLE_CLASSES_FOUND = "JC_classes_found"; // NOI18N
private static final String BUNDLE_CLASSES_DONE = "JC_classes_done"; // NOI18N
private static final String BUNDLE_CLASSES_DONE_OF = "JC_classes_done_of"; // NOI18N
Node[] activatedNodes;
ProgressPanel progress;
Map lookupCache;
int doneCnt;
public JCUpdater(Node[] activatedNodes) {
this.activatedNodes = activatedNodes;
// setPriority(Thread.MIN_PRIORITY);
setName("ParserDB Updater"); // NOI18N
}
public void run() {
try {
progress = new ProgressPanel();
progress.setDialogVisible(true);
lookupCache = new HashMap(1009);
Node[] nodes = (Node[])activatedNodes.clone();
activatedNodes = null;
for (int i = 0; i < nodes.length; i++) {
Node n = nodes[i];
progress.invokeSetBuilding(getBundleString(BUNDLE_INSPECTING));
progress.invokeSetCurrentClass(""); // NOI18N
progress.invokeSetDoneString(""); // NOI18N
if (!processNode(n, progress)) {
break;
}
nodes[i] = null;
}
lookupCache.clear();
lookupCache = null;
progress.destroy();
progress = null;
} catch (Throwable t) {
System.err.println("Exception occurred during parser database rebuilding"); // NOI18N
t.printStackTrace();
}
}
boolean processNode(Node n, ProgressPanel progress) {
QueueEnumeration qe = new QueueEnumeration();
int cnt = 0;
boolean root = false;
String fsName = null;
DataFolder df = (DataFolder)n.getCookie(DataFolder.class);
try {
if (df != null) { // data folder
inspectFolder(df, qe);
cnt = doneCnt;
doneCnt = 0;
FileObject fo = df.getPrimaryFile();
fsName = fo.getFileSystem().getSystemName();
root = fo.isRoot();
} else {
SourceCookie sc = (SourceCookie)n.getCookie(SourceCookie.class);
if (sc != null) {
cnt = 1;
qe.put(sc);
fsName = ((DataObject)n.getCookie(DataObject.class)).getPrimaryFile(
).getFileSystem().getSystemName();
}
}
} catch (FileStateInvalidException e) {
// fsName will be null
}
// process queue
if (cnt > 0 && fsName != null) {
return updateProvider(qe, cnt, fsName, root, progress);
}
return true;
}
void inspectFolder(DataFolder df, QueueEnumeration qe) {
DataObject[] children = df.getChildren();
children = (DataObject[])children.clone();
for (int i = 0; i < children.length; i++) {
DataObject dob = children[i];
if (dob instanceof DataFolder) {
inspectFolder((DataFolder)dob, qe);
} else {
SourceCookie sc = (SourceCookie)dob.getCookie(SourceCookie.class);
if (sc != null) {
qe.put(sc);
doneCnt++;
progress.invokeSetCurrentClass(doneCnt + ' ' + getBundleString(BUNDLE_CLASSES_FOUND));
}
}
children[i] = null;
}
}
boolean updateProvider(final QueueEnumeration qe, final int classCnt,
String fsName, boolean isRoot, final ProgressPanel progress) {
// Get provider
JCStorage storage = JCStorage.getStorage();
JCStorageElement element = storage.findFileSystemElement(fsName);
if (isRoot || element == null) { // not yet created
progress.setDialogVisible(false);
// Display dialog with options
JCProviderPanel pp = new JCProviderPanel();
if (element != null) {
pp.setNamePrefix(element.getName());
pp.setClassLevel(element.getClassLevel());
pp.setFieldLevel(element.getFieldLevel());
pp.setMethodLevel(element.getMethodLevel());
}
DialogDescriptor dd = new DialogDescriptor(pp,
getBundleString(BUNDLE_TITLE) + ' ' + fsName);
Dialog d = TopManager.getDefault().createDialog(dd);
d.pack();
d.setVisible(true);
Object o = dd.getValue();
if (o == DialogDescriptor.OK_OPTION) {
element = storage.addElement(pp.getNamePrefix(), fsName,
pp.getClassLevel(), pp.getFieldLevel(), pp.getMethodLevel());
} else { // cancel pressed
d.setVisible(false);
d.dispose();
d = null;
return false;
}
progress.setDialogVisible(true);
}
final int classLevel = element.getClassLevel();
final int fieldLevel = element.getFieldLevel();
final int methodLevel = element.getMethodLevel();
storage.checkProvider(element);
// Update provider classes
final String doneString = " " + getBundleString(BUNDLE_CLASSES_DONE); // NOI18N
final String ofString = " " + getBundleString(BUNDLE_CLASSES_DONE_OF) + " "; // NOI18N
final JCompletion.ListProvider classes = new JCompletion.ListProvider() {
protected boolean appendClass(JCClass c) {
super.appendClass(c);
progress.invokeSetCurrentClass(c.getFullName());
return !progress.cancelled;
}
public boolean notifyAppend(JCClass c, boolean appendFinished) {
if (appendFinished) {
doneCnt++;
progress.invokeSetDoneString(doneCnt + ofString + classCnt + doneString);
} else { // not finished
progress.invokeSetCurrentClass(c.getFullName());
}
return !progress.cancelled;
}
};
// Build class list
progress.invokeSetBuilding(getBundleString(BUNDLE_BUILDING_CLASS));
progress.invokeSetDoneString(getBundleString(BUNDLE_INIT_PARSER));
boolean ok = true;
doneCnt = 0;
while (ok && qe.hasMoreElements()) {
SourceCookie sc = (SourceCookie)qe.nextElement();
SourceElement se = sc.getSource();
ClassElement ce[] = se.getAllClasses();
if (ce != null) {
for (int i = 0; i < ce.length; i++) {
JCClass classToAppend = JCExtension.parseClassElement(ce[i], classLevel,
fieldLevel, methodLevel, lookupCache, false);
if (classToAppend != null) {
if (!classes.append(new JCompletion.SingleProvider(classToAppend))) {
ok = false;
break;
}
}
}
}
doneCnt++;
progress.invokeSetDoneString(doneCnt + ofString + classCnt + doneString);
}
if (!ok) {
return false;
}
// Update database
doneCnt = 0;
progress.invokeSetBuilding(getBundleString(BUNDLE_UPDATING_DB));
element.getProvider().append(classes);
// Update in-memory copy
doneCnt = 0;
progress.invokeSetBuilding(getBundleString(BUNDLE_UPDATING_MEMORY));
JCompletion.getFinder().append(classes);
return true;
}
String getBundleString(String s) {
if (bundle == null) {
bundle = NbBundle.getBundle(JCProviderPanel.class);
}
return bundle.getString(s);
}
class ProgressPanel extends JCProgressPanel
implements ActionListener {
private DialogDescriptor descriptor;
Dialog dialog;
boolean cancelled;
static final long serialVersionUID =6306529202240892814L;
ProgressPanel() {
}
DialogDescriptor getDescriptor() {
if (descriptor == null) {
descriptor = createDescriptor();
}
return descriptor;
}
DialogDescriptor createDescriptor() {
return new DialogDescriptor(this,
getBundleString("JC_progress_title"), // NOI18N
false,
new Object[] { DialogDescriptor.CANCEL_OPTION },
DialogDescriptor.CANCEL_OPTION, DialogDescriptor.BOTTOM_ALIGN,
new HelpCtx(JCExtension.class),
this
);
}
public void actionPerformed(ActionEvent evt) {
if (evt.getSource() instanceof javax.swing.JButton) { // how better? !!!
cancelPressed();
}
}
void cancelPressed() {
cancelled = true;
setDialogVisible(false);
}
void setDialogVisible(final boolean visible) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
if (visible && dialog == null) {
dialog = TopManager.getDefault().createDialog(getDescriptor());
dialog.setSize(300, 200);
}
if (dialog != null) {
dialog.setVisible(visible);
}
}
}
);
}
void destroy() {
if (dialog != null) {
dialog.setVisible(false);
dialog.dispose();
dialog = null;
}
descriptor = null;
}
}
}
/*
* Log
* 12 Gandalf 1.11 1/13/00 Miloslav Metelka Localization
* 11 Gandalf 1.10 12/28/99 Miloslav Metelka
* 10 Gandalf 1.9 11/14/99 Miloslav Metelka
* 9 Gandalf 1.8 11/11/99 Miloslav Metelka
* 8 Gandalf 1.7 11/8/99 Miloslav Metelka
* 7 Gandalf 1.6 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 6 Gandalf 1.5 9/15/99 Miloslav Metelka
* 5 Gandalf 1.4 8/9/99 Ian Formanek Generated Serial Version
* UID
* 4 Gandalf 1.3 7/22/99 Miloslav Metelka
* 3 Gandalf 1.2 7/21/99 Miloslav Metelka
* 2 Gandalf 1.1 7/21/99 Miloslav Metelka
* 1 Gandalf 1.0 7/20/99 Miloslav Metelka
* $
*/